package org.mx.test.config;

import javax.persistence.EntityManager;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import org.mx.dal.config.DalConfig;
import org.mx.dal.config.DalHibernateConfig;
import org.mx.dal.service.EntityManagerService;
import org.mx.dal.service.GeneralAccessor;
import org.mx.dal.service.GeneralDictAccessor;
import org.mx.dal.service.impl.GeneralAccessorImpl;
import org.mx.dal.service.impl.GeneralDictAccessorImpl;
import org.mx.dbcp.MyDbcp2DataSourceFactoryUtil;
import org.mx.error.UserInterfaceException;
import org.mx.spring.session.SessionDataStore;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;

/**
 * 基于Hibernate的DAL基础实现，从RDB继承而来。
 *
 * @author : john.peng date : 2017/10/7
 * @see DalConfig
 */
@SuppressWarnings("javadoc")
@EnableTransactionManagement
public class DalHibernateTest1Config {


	/**
	 * 创建atomikos用户事务
	 * @return 用户事务
	 */
	@Bean("atomikosUserTransaction")
	public UserTransaction atomikosUserTransaction() {
		UserTransaction transaction = new UserTransactionImp();
		try {
			transaction.setTransactionTimeout(300);
		} catch (SystemException ex) {
			throw new UserInterfaceException(-1, "Set transaction timeout to 300s fail.", ex);
		}
		return transaction;
	}

	/**
	 * 创建atomikos用户事务管理器
	 * @return 用户事务管理器
	 */
	@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
	public UserTransactionManager atomikosUserTransactionManager() {
		UserTransactionManager transactionManager = new UserTransactionManager();
		transactionManager.setForceShutdown(true);
		try {
			transactionManager.setTransactionTimeout(300);
		} catch (SystemException ex) {
			throw new UserInterfaceException(-1, "Set transaction timeout to 300s fail.", ex);
		}
		return transactionManager;
	}

	/**
	 * 创建JTA事务管理器
	 * @param userTransaction 用户事务
	 * @param userTransactionManager 用户事务管理器
	 * @return JTA事务管理器
	 */
	@Bean(name = "transactionManager")
	public JtaTransactionManager jtaTransactionManager(
			@Qualifier("atomikosUserTransaction") UserTransaction userTransaction,
			@Qualifier("atomikosTransactionManager") UserTransactionManager userTransactionManager) {
		JtaTransactionManager jta = new JtaTransactionManager(userTransaction, userTransactionManager);
		jta.setAllowCustomIsolationLevels(true);
		return jta;
	}
	
	/**
	 * 创建实体管理器工厂Bean
	 *
	 * @param env       Spring IoC环境
	 * @param util		数据库连接池工厂集合，可以根据配置名访问
	 * @return 实体管理器工厂Bean
	 */
	@Bean("entityManagerFactoryTest1")
	public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(Environment env,
			MyDbcp2DataSourceFactoryUtil util) {
		return DalHibernateConfig.createEntityManagerFactoryBean(env, util, "test1", "jpa1");
	}

	/**
	 * 创建一个实体管理器
	 * @param emfb 实体管理工厂Bean
	 * @return EntityManager
	 */
	@Bean("entityManagerTest1")
	public EntityManager entityManager(
			@Qualifier("entityManagerFactoryTest1") LocalContainerEntityManagerFactoryBean emfb) {
		return emfb.getObject().createEntityManager();
	}

	/**
	 * 创建事务管理器
	 *
	 * @param containerEntityManagerFactoryBean 实体管理器工厂Bean
	 * @return 事务管理器
	 */
	@Bean("transactionManagerTest1")
	public PlatformTransactionManager transactionManager(
			@Qualifier("entityManagerFactoryTest1") LocalContainerEntityManagerFactoryBean containerEntityManagerFactoryBean) {
		return new JpaTransactionManager(containerEntityManagerFactoryBean.getObject());
	}

	/**
	 * 创建基于JPA的数据对象Accessor
	 * 
	 * @param sessionDataStore 会话数据存储
	 * @return Accessor
	 */
	@Bean(name = "generalAccessorJpaTest1")
	public GeneralAccessor generalAccessorJpa(
			@Qualifier("entityManagerServiceTest1") EntityManagerService entityManagerService,
			SessionDataStore sessionDataStore) {
		return new GeneralAccessorImpl(entityManagerService, sessionDataStore);
	}

	/**
	 * 创建基于JPA的字典对象Accessor
	 * 
	 * @param sessionDataStore 会话数据存储
	 * @return Accessor
	 */
	@Bean(name = "generalDictAccessorJpaTest1")
	public GeneralDictAccessor generalDictAccessorJpa(
			@Qualifier("entityManagerServiceTest1") EntityManagerService entityManagerService,
			SessionDataStore sessionDataStore) {
		return new GeneralDictAccessorImpl(entityManagerService, sessionDataStore);
	}

	/**
	 * 创建一个通用的数据访问器
	 *
	 * @param context Spring IoC上下文
	 * @return 数据访问器
	 */
	@Bean(name = "generalAccessorTest1")
	public GeneralAccessor generalAccessor(ApplicationContext context) {
		return context.getBean("generalAccessorJpaTest1", GeneralAccessor.class);
	}

	/**
	 * 创建一个通用的字典数据访问器
	 *
	 * @param context Spring IoC上下文
	 * @return 数据访问器
	 */
	@Bean(name = "generalDictAccessorTest1")
	public GeneralDictAccessor generalDictAccessor(ApplicationContext context) {
		return context.getBean("generalDictAccessorJpaTest1", GeneralDictAccessor.class);
	}
}
